package com.hgw.poippt.lcn.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.hgw.poippt.lcn.data.RequirementPptData;
import com.hgw.poippt.lcn.data.RequirementPptPlaceholderEnum;
import lombok.extern.slf4j.Slf4j;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.sl.usermodel.PictureData;
import org.apache.poi.sl.usermodel.TableCell;
import org.apache.poi.sl.usermodel.TextParagraph;
import org.apache.poi.sl.usermodel.VerticalAlignment;
import org.apache.poi.xslf.usermodel.*;
import org.assertj.core.util.Lists;

import java.awt.*;
import java.awt.geom.Rectangle2D;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.List;

/**
 * Description: 需求PPT生成器
 *
 * @author LinHuiBa-YanAn
 * @date 2023/5/25 20:35
 */
@Slf4j
public class RequirementPptGenerate {
    /**
     * ppt
     */
    private XMLSlideShow ppt;
    /**
     * 幻灯片下标（ 每次执行时幻灯片的下标））
     */
    private int slideIndex = 0;
    /**
     * PPT数据体
     */
    private final RequirementPptData data;
    /**
     * 模版ppt文件存储链接（调整由Nacos配置中心读取配置文件）
     */
    private final String TEMPLATE_PPT_URI = "https://middle-file.linhuiba.com/lgwnhdJLniR-pNSfWGTFKa-f39il";

    /**
     * 构造方法
     *
     * @param data PPT数据源
     */
    public RequirementPptGenerate(RequirementPptData data) {
        this.data = data;
    }

    /**
     * 初始化PPT文件
     */
    private void initPpt() {
        InputStream originalFis = getInputStream(TEMPLATE_PPT_URI);
        try {
            ppt = new XMLSlideShow(originalFis);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                originalFis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        this.slideIndex = 0;
    }

    /**
     * 生成PPT
     *
     * @return PPT文件于七牛云的存储路径
     */
    public String generatePpt() throws Exception {
        initPpt();
        if (data == null) {
            throw new Exception("PPT数据体不能为空");
        }
        assemblePpt();
        return uploadFileToOss(ppt);
    }

    /**
     * 组装PPT
     */
    private void assemblePpt() {
        // 拼装封面幻灯片
        assembleHomePageSlide();
        // 拼装需求描述幻灯片
        assembleRequirementSlide();
        // 拼装案例介绍幻灯片
        assembleActivitySlide();
        // 拼装选址策略幻灯片
        assembleLocationStrategySlide();
        // 拼装场地清单幻灯片
        assembleSpotSlide();
        // 拼接场地详情幻灯片
        assemblePlaceDetailSlide();
        // 拼接细化需求内容幻灯片
        assembleDetailedRequirementContentSlide();
        // 拼装结束页幻灯片
        assembleEndSlide();
    }

    /**
     * 拼装封面幻灯片
     */
    private void assembleHomePageSlide() {
        XSLFSlide slide = ppt.getSlides().get(slideIndex++);
        if (slide != null) {
            List<XSLFShape> shapes = slide.getShapes();
            shapes.forEach(shape -> {
                // 填充文本框数据
                if (shape instanceof XSLFTextBox) {
                    XSLFTextBox textBox = (XSLFTextBox) shape;
                    if (CollUtil.isNotEmpty(textBox.getTextParagraphs()) && CollUtil.isNotEmpty(textBox.getTextParagraphs().get(0).getTextRuns())) {
                        String text = textBox.getText();
                        if (text.contains(RequirementPptPlaceholderEnum.REQUIREMENT_NAME.getValue())) {
                            text = text.replace(RequirementPptPlaceholderEnum.REQUIREMENT_NAME.getValue(), ObjectUtil.isNotEmpty(data.getRequirementName()) ? data.getRequirementName() : "");
                            textBox.setText(text);
                            XSLFTextRun textRun = textBox.getTextParagraphs().get(0).getTextRuns().get(0);
                            textRun.setFontColor(Color.WHITE);
                            textRun.setFontFamily("SimSun");
                            textRun.setFontSize(32.00);
                            textRun.setBold(true);
                        }
                    }
                }
            });
        }
    }

    /**
     * 拼装需求描述幻灯片
     */
    private void assembleRequirementSlide() {
        XSLFSlide slide = ppt.getSlides().get(slideIndex++);
        if (slide != null) {
            int addNum = 0;
            List<Boolean> lists = Lists.list(StringUtils.isNotEmpty(data.getBrand()), StringUtils.isNotEmpty(data.getIndustry()), StringUtils.isNotEmpty(data.getPromotionTime()), StringUtils.isNotEmpty(data.getCity()), StringUtils.isNotEmpty(data.getTargetScenario()), StringUtils.isNotEmpty(data.getSpotCategory()), StringUtils.isNotEmpty(data.getArea()), StringUtils.isNotEmpty(data.getActiveBudget()));
            long count = 0;
            if (CollUtil.isNotEmpty(lists)) {
                count = lists.stream().filter(b -> !b).count();
            }
            double h = 20 * count;
            if (StringUtils.isNotEmpty(data.getBrand())) {
                slideAddText(slide, new Rectangle2D.Double(40, 130 + (40 * addNum++) + h, 260, 60), "推广品牌：" + data.getBrand(), VerticalAlignment.MIDDLE, false, 18.00, Color.white);
            }
            if (StringUtils.isNotEmpty(data.getIndustry())) {
                slideAddText(slide, new Rectangle2D.Double(40, 130 + (40 * addNum++) + h, 260, 60), "所属行业：" + data.getIndustry(), VerticalAlignment.MIDDLE, false, 18.00, Color.white);
            }
            if (StringUtils.isNotEmpty(data.getPromotionTime())) {
                slideAddText(slide, new Rectangle2D.Double(40, 130 + (40 * addNum++) + h, 260, 60), "活动时间：" + data.getPromotionTime(), VerticalAlignment.MIDDLE, false, 18.00, Color.white);
            }
            if (StringUtils.isNotEmpty(data.getCity())) {
                slideAddText(slide, new Rectangle2D.Double(40, 130 + (40 * addNum++) + h, 260, 60), "需求城市：" + data.getCity(), VerticalAlignment.MIDDLE, false, 18.00, Color.white);
            }
            if (StringUtils.isNotEmpty(data.getTargetScenario())) {
                slideAddText(slide, new Rectangle2D.Double(40, 130 + (40 * addNum++) + h, 260, 60), "营销场景：" + data.getTargetScenario(), VerticalAlignment.MIDDLE, false, 18.00, Color.white);
            }
            if (StringUtils.isNotEmpty(data.getSpotCategory())) {
                slideAddText(slide, new Rectangle2D.Double(40, 130 + (40 * addNum++) + h, 260, 60), "位置要求：" + data.getSpotCategory(), VerticalAlignment.MIDDLE, false, 18.00, Color.white);
            }
            if (StringUtils.isNotEmpty(data.getArea())) {
                slideAddText(slide, new Rectangle2D.Double(40, 130 + (40 * addNum++) + h, 260, 60), "面积要求：" + data.getArea(), VerticalAlignment.MIDDLE, false, 18.00, Color.white);
            }
            if (StringUtils.isNotEmpty(data.getActiveBudget())) {
                slideAddText(slide, new Rectangle2D.Double(40, 130 + (40 * addNum++) + h, 260, 60), "单场预算：" + data.getActiveBudget(), VerticalAlignment.MIDDLE, false, 18.00, Color.white);
            }
        }
    }

    /**
     * 拼装案例介绍幻灯片
     */
    private void assembleActivitySlide() {
        // 案例数量少于2个，则删除“案例介绍”幻灯片
        if (CollUtil.isEmpty(data.getActivityList()) || data.getActivityList().size() < 2) {
            ppt.removeSlide(slideIndex);
            return;
        }
        XSLFSlide slide = ppt.getSlides().get(slideIndex++);
        // 添加案例图片
        int count = 0;
        for (RequirementPptData.ActivityData activityData : data.getActivityList()) {
            if (ObjectUtil.isNotEmpty(activityData.getPictureUri())) {
                String pictureUri = activityData.getPictureUri();
                XSLFPictureData pictureData = null;
                try {
                    pictureData = ppt.addPicture(getInputStream(pictureUri), PictureData.PictureType.PNG);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                if (pictureData != null) {
                    XSLFPictureShape pictureShape = slide.createPicture(pictureData);
                    int x = (count > 0 ? count * 300 + 30 : 30);
                    pictureShape.setAnchor(new Rectangle(x, 150, 290, 220));
                    // 图片标题
                    if (ObjectUtil.isNotEmpty(activityData.getActivityName())) {
                        XSLFTextBox textBox = slide.createTextBox();
                        textBox.setText(activityData.getActivityName());
                        textBox.setVerticalAlignment(VerticalAlignment.MIDDLE);
                        textBox.setAnchor(new Rectangle2D.Double(x, 400, 290, 20));
                        XSLFTextParagraph paragraph = textBox.getTextParagraphs().get(0);
                        paragraph.setTextAlign(TextParagraph.TextAlign.CENTER);
                        XSLFTextRun textRun = paragraph.getTextRuns().get(0);
                        textRun.setBold(false);
                        textRun.setFontSize(18.00);
                    }
                    count++;
                }
            }
            // 一页最多三张案例图片
            if (count >= 3) {
                break;
            }
        }
        // 添加超链接
        slideAddLink(slide, new Rectangle2D.Double(780, 460, 200, 20), "点此查看所有案例>", data.getAllActivityUri());
    }

    /**
     * 拼装选址策略幻灯片
     */
    private void assembleLocationStrategySlide() {
        // 0608版本中该幻灯片页保持模版幻灯片不修改
        slideIndex++;
        return;
    }

    /**
     * 拼装场地清单幻灯片
     */
    private void assembleSpotSlide() {
        List<RequirementPptData.SpotData> spotList = data.getSpotList();
        // 数组总长度
        int spotListSize = 0;
        // 数组下标
        int spotListIndex = 0;
        if (CollUtil.isNotEmpty(spotList)) {
            spotListSize = spotList.size();
        }
        // 场地清单第一张幻灯片（4条）
        XSLFSlide firstSpotSlide = ppt.getSlides().get(slideIndex++);
        spotListIndex = buildSpotSlide(spotList, spotListIndex, firstSpotSlide);
        spotListSize = spotListSize - 4;
        if (spotListSize > 0) {
            // 场地清单第二张幻灯片（7条）
            while (true) {
                spotListIndex = insertSpotListSlide(slideIndex++, spotList, spotListIndex);
                spotListSize -= 7;
                if (spotListSize <= 0) {
                    break;
                }
            }
        }
    }

    /**
     * 拼装场地详情幻灯片
     */
    private void assemblePlaceDetailSlide() {
        if (CollUtil.isEmpty(data.getPlaceList())) {
            return;
        }
        List<RequirementPptData.PlaceData> placeList = data.getPlaceList();
        for (RequirementPptData.PlaceData placeData : placeList) {
            insertPlaceDetailSlideSlide(slideIndex++, placeData);
        }
    }

    private void insertPlaceDetailSlideSlide(Integer newIndex, RequirementPptData.PlaceData placeData) {
        XSLFSlide newSlide = ppt.createSlide();
        newSlide.clear();
        // 标题前矩形
        XSLFAutoShape beforeTitleRectangle = newSlide.createAutoShape();
        beforeTitleRectangle.setAnchor(new Rectangle2D.Double(0, 42, 30, 30));
        beforeTitleRectangle.setFillColor(new Color(22, 102, 240));
        // 标题
        slideAddText(newSlide, new Rectangle2D.Double(40, 42, 200, 30), placeData.getName(), VerticalAlignment.MIDDLE, true, 28.00, null);
        // 内容底矩形
        XSLFAutoShape contextRectangle = newSlide.createAutoShape();
        contextRectangle.setAnchor(new Rectangle2D.Double(400, 42, 530, 338));
        contextRectangle.setFillColor(new Color(242, 242, 242));
        // 内容插入
        slideAddText(newSlide, new Rectangle2D.Double(420, 60, 100, 30), "商业体量", VerticalAlignment.MIDDLE, true, 18.00, null);
        slideAddText(newSlide, new Rectangle2D.Double(700, 60, 100, 30), "客流概况", VerticalAlignment.MIDDLE, true, 18.00, null);
        slideAddText(newSlide, new Rectangle2D.Double(420, 150, 100, 30), "客群客质", VerticalAlignment.MIDDLE, true, 18.00, null);
        slideAddText(newSlide, new Rectangle2D.Double(700, 150, 100, 30), "区位优势", VerticalAlignment.MIDDLE, true, 18.00, null);
        slideAddText(newSlide, new Rectangle2D.Double(420, 240, 100, 30), "过往案例", VerticalAlignment.MIDDLE, true, 18.00, null);
        slideAddText(newSlide, new Rectangle2D.Double(700, 240, 100, 30), "周边竞品", VerticalAlignment.MIDDLE, true, 18.00, null);
        if (ObjectUtil.isNotEmpty(placeData.getCommercialVolume())) {
            slideAddText(newSlide, new Rectangle2D.Double(420, 90, 250, 60), placeData.getCommercialVolume(), VerticalAlignment.TOP, false, 18.00, null);
        }
        if (ObjectUtil.isNotEmpty(placeData.getFlow())) {
            slideAddText(newSlide, new Rectangle2D.Double(700, 90, 250, 60), placeData.getFlow(), VerticalAlignment.TOP, false, 18.00, null);
        }
        if (ObjectUtil.isNotEmpty(placeData.getCrowdQuality())) {
            slideAddText(newSlide, new Rectangle2D.Double(420, 180, 250, 60), placeData.getCrowdQuality(), VerticalAlignment.TOP, false, 18.00, null);
        }
        if (ObjectUtil.isNotEmpty(placeData.getBusinessCircle())) {
            slideAddText(newSlide, new Rectangle2D.Double(700, 180, 250, 60), placeData.getBusinessCircle(), VerticalAlignment.TOP, false, 18.00, null);
        }
        if (ObjectUtil.isNotEmpty(placeData.getPastActivity())) {
            slideAddText(newSlide, new Rectangle2D.Double(420, 270, 250, 60), placeData.getPastActivity(), VerticalAlignment.TOP, false, 18.00, null);
        }
        if (ObjectUtil.isNotEmpty(placeData.getSurroundingBrands())) {
            slideAddText(newSlide, new Rectangle2D.Double(700, 270, 250, 60), placeData.getSurroundingBrands(), VerticalAlignment.TOP, false, 18.00, null);
        }
        // 图片插入
        if (ObjectUtil.isNotEmpty(placeData.getPlacePictureUri())) {
            try {
                InputStream inputStream = getInputStream(placeData.getPlacePictureUri());
                if (inputStream != null) {
                    XSLFPictureData pictureData = ppt.addPicture(inputStream, PictureData.PictureType.PNG);
                    XSLFPictureShape pictureShape = newSlide.createPicture(pictureData);
                    pictureShape.setAnchor(new Rectangle(40, 100, 350, 280));
                }
            } catch (IOException e) {
                log.error("导出需求PPT出错：插入图片文件出错！", e.getMessage());
            }
        }
        // 添加超链接
        if (ObjectUtil.isNotEmpty(placeData.getPlaceDetailUri())) {
            slideAddLink(newSlide, new Rectangle2D.Double(550, 320, 280, 20), "点击查看更多场地信息和案例", placeData.getPlaceDetailUri());
        }
        // 表格
        String[] titles = new String[]{"展位位置", "楼层", "面积", "推荐理由"};
        XSLFTable table = newSlide.createTable(3, titles.length);
        table.setAnchor(new Rectangle2D.Double(40, 400, 800, 200));
        for (int r = 0; r < table.getRows().size(); r++) {
            table.setRowHeight(r, 40);
        }
        XSLFTableRow titleRow = table.getRows().get(0);
        for (int i = 0; i < titleRow.getCells().size(); i++) {
            if (i == (titleRow.getCells().size() - 1)) {
                table.setColumnWidth(i, 450);
            } else {
                table.setColumnWidth(i, 150);
            }
            XSLFTableCell cell = titleRow.getCells().get(i);
            cell.setFillColor(new Color(22, 102, 240));
            cell.setBorderColor(TableCell.BorderEdge.top, new Color(211, 211, 211));
            cell.setBorderColor(TableCell.BorderEdge.bottom, new Color(211, 211, 211));
            cell.setBorderColor(TableCell.BorderEdge.left, new Color(211, 211, 211));
            cell.setBorderColor(TableCell.BorderEdge.right, new Color(211, 211, 211));
            cell.setVerticalAlignment(VerticalAlignment.MIDDLE);
            XSLFTextRun textRun = cell.setText(titles[i]);
            textRun.setFontColor(Color.WHITE);
            textRun.setBold(Boolean.TRUE);
            textRun.setFontSize(14.00);
        }
        if (CollUtil.isNotEmpty(placeData.getSpotList())) {
            for (int row = 1; row < table.getNumberOfRows(); row++) {
                if (row > placeData.getSpotList().size()) {
                    break;
                }
                RequirementPptData.SpotData spotData = placeData.getSpotList().get(row - 1);
                for (int colum = 0; colum < table.getNumberOfColumns(); colum++) {
                    // 遍历单元格匹配修改内容
                    XSLFTableCell cell = table.getCell(row, colum);
                    cell.setBorderColor(TableCell.BorderEdge.top, new Color(211, 211, 211));
                    cell.setBorderColor(TableCell.BorderEdge.bottom, new Color(211, 211, 211));
                    cell.setBorderColor(TableCell.BorderEdge.left, new Color(211, 211, 211));
                    cell.setBorderColor(TableCell.BorderEdge.right, new Color(211, 211, 211));
                    cell.setVerticalAlignment(VerticalAlignment.MIDDLE);
                    String text = "";
                    // 展位位置
                    if (colum == 0) {
                        text = spotData.getName();
                    }
                    // 楼层
                    if (colum == 1) {
                        text = spotData.getFloor();
                    }
                    // 面积
                    if (colum == 2) {
                        text = spotData.getArea();
                    }
                    // 推荐理由（点位介绍）
                    if (colum == 3) {
                        text = spotData.getDescription();
                    }
                    XSLFTextRun textRun = cell.setText(text);
                    textRun.setFontColor(Color.BLACK);
                    textRun.setBold(Boolean.FALSE);
                    textRun.setFontSize(14.00);
                }
            }
        }
        // 排序（在PPT中的第几页）
        ppt.setSlideOrder(newSlide, newIndex);
    }

    /**
     * 填充场地详情幻灯片
     *
     * @param placeData 场地信息
     * @param slide     幻灯片
     */
    public void buildPlaceDetailSlide(RequirementPptData.PlaceData placeData, XSLFSlide slide) {
        // 标题
        if (ObjectUtil.isNotEmpty(placeData.getName())) {
            slideAddText(slide, new Rectangle2D.Double(40, 42, 200, 30), placeData.getName(), VerticalAlignment.MIDDLE, true, 28.00, null);
        }
        // 内容插入
        slideAddText(slide, new Rectangle2D.Double(420, 100, 100, 30), "商业体量", VerticalAlignment.MIDDLE, true, 18.00, null);
        slideAddText(slide, new Rectangle2D.Double(700, 100, 100, 30), "客流概况", VerticalAlignment.MIDDLE, true, 18.00, null);
        slideAddText(slide, new Rectangle2D.Double(420, 190, 100, 30), "客群客质", VerticalAlignment.MIDDLE, true, 18.00, null);
        slideAddText(slide, new Rectangle2D.Double(700, 190, 100, 30), "区位优势", VerticalAlignment.MIDDLE, true, 18.00, null);
        slideAddText(slide, new Rectangle2D.Double(420, 280, 100, 30), "过往案例", VerticalAlignment.MIDDLE, true, 18.00, null);
        slideAddText(slide, new Rectangle2D.Double(700, 280, 100, 30), "周边竞品", VerticalAlignment.MIDDLE, true, 18.00, null);
        if (ObjectUtil.isNotEmpty(placeData.getCommercialVolume())) {
            slideAddText(slide, new Rectangle2D.Double(420, 130, 250, 60), placeData.getCommercialVolume(), VerticalAlignment.TOP, false, 18.00, null);
        }
        if (ObjectUtil.isNotEmpty(placeData.getFlow())) {
            slideAddText(slide, new Rectangle2D.Double(700, 130, 250, 60), placeData.getFlow(), VerticalAlignment.TOP, false, 18.00, null);
        }
        if (ObjectUtil.isNotEmpty(placeData.getCrowdQuality())) {
            slideAddText(slide, new Rectangle2D.Double(420, 220, 250, 60), placeData.getCrowdQuality(), VerticalAlignment.TOP, false, 18.00, null);
        }
        if (ObjectUtil.isNotEmpty(placeData.getBusinessCircle())) {
            slideAddText(slide, new Rectangle2D.Double(700, 220, 250, 60), placeData.getBusinessCircle(), VerticalAlignment.TOP, false, 18.00, null);
        }
        if (ObjectUtil.isNotEmpty(placeData.getPastActivity())) {
            slideAddText(slide, new Rectangle2D.Double(420, 310, 250, 60), placeData.getPastActivity(), VerticalAlignment.TOP, false, 18.00, null);
        }
        if (ObjectUtil.isNotEmpty(placeData.getSurroundingBrands())) {
            slideAddText(slide, new Rectangle2D.Double(700, 310, 250, 60), placeData.getSurroundingBrands(), VerticalAlignment.TOP, false, 18.00, null);
        }
        // 图片插入
        if (ObjectUtil.isNotEmpty(placeData.getPlaceDetailUri())) {
            String pictureUri = placeData.getPlacePictureUri();
            XSLFPictureData pictureData = null;
            try {
                pictureData = ppt.addPicture(getInputStream(pictureUri), PictureData.PictureType.PNG);
            } catch (IOException e) {
                e.printStackTrace();
            }
            if (pictureData != null) {
                XSLFPictureShape pictureShape = slide.createPicture(pictureData);
                pictureShape.setAnchor(new Rectangle(40, 100, 350, 280));
            }
        }
        // 添加超链接
        slideAddLink(slide, new Rectangle2D.Double(550, 370, 260, 20), "点击查看更多场地信息和案例", placeData.getPlaceDetailUri());
        // 表格填充
        for (XSLFShape shape : slide.getShapes()) {
            if (shape instanceof XSLFTable) {
                // 填充表格内数据
                XSLFTable table = (XSLFTable) shape;
                if (CollUtil.isNotEmpty(placeData.getSpotList())) {
                    for (int row = 1; row < table.getNumberOfRows(); row++) {
                        if (row > placeData.getSpotList().size()) {
                            break;
                        }
                        RequirementPptData.SpotData spotData = placeData.getSpotList().get(row - 1);
                        for (int colum = 0; colum < table.getNumberOfColumns(); colum++) {
                            // 遍历单元格匹配修改内容
                            XSLFTableCell cell = table.getCell(row, colum);
                            String text = "";
                            // 展位位置
                            if (colum == 0) {
                                text = spotData.getName();
                            }
                            // 楼层
                            if (colum == 1) {
                                text = spotData.getFloor();
                            }
                            // 面积
                            if (colum == 2) {
                                text = spotData.getArea();
                            }
                            // 推荐理由（点位介绍）
                            if (colum == 3) {
                                text = spotData.getDescription();
                            }
                        }
                    }
                }

            }
        }
    }

    /**
     * 拼接细化需求内容幻灯片
     */
    private void assembleDetailedRequirementContentSlide() {
        if (data == null) {
            return;
        }
        List<Boolean> booleanList = Arrays.asList(data.getIsFillCategory(), data.getIsFillSpotCategory(), data.getIsFillArea(), data.getIsFillDayActiveBudget());
        // 未填充计数
        long isNotFillCount = booleanList.stream().filter(b -> (b == null || !b)).count();
        if (isNotFillCount < 2) {
            // 未填写字段小于2时不展示需求内容幻灯片
            ppt.removeSlide(slideIndex);
            return;
        }
        // 内容插入
        XSLFSlide slide = ppt.getSlides().get(slideIndex++);
        if (ObjectUtil.isNotEmpty(data.getPublisher())) {
            RequirementPptData.EmployeeData publisher = data.getPublisher();
            if (StringUtils.isNotEmpty(publisher.getName())) {
                slideAddText(slide, new Rectangle2D.Double(50, 55, 200, 50), publisher.getName(), VerticalAlignment.MIDDLE, true, 28.00, null);
            }/* try {
                    InputStream inputStream = getInputStream(publisher.getQrCodeUrl());
                    if (inputStream != null) {
                        XSLFPictureData pictureData = ppt.addPicture(inputStream, PictureData.PictureType.PNG);
                        XSLFPictureShape pictureShape = slide.createPicture(pictureData);
                        pictureShape.setAnchor(new Rectangle(230, 60, 100, 100));
                    }
                } catch (IOException e) {
                    log.error("导出需求PPT出错：插入图片文件出错！", e.getMessage());
                }*/
            slideAddText(slide, new Rectangle2D.Double(50, 125, 150, 50), "18755777113", VerticalAlignment.MIDDLE, true, 20.00, null);
        }
        // 需求是否填写营销场景(目标场景)
        int addNum = 0;
        if (!data.getIsFillCategory()) {
            addNum = slideAddMsgShape(slide, addNum, "营销场景", "商场&写字楼", "过去家电行业70%的线下选择");
        }
        if (!data.getIsFillSpotCategory()) {
            addNum = slideAddMsgShape(slide, addNum, "位置", "连廊", "数据表明，连廊客流量大约为中庭的80%，但价格是中庭的1/10-1/5");
        }
        if (!data.getIsFillArea()) {
            addNum = slideAddMsgShape(slide, addNum, "面积", "20-40平", "数据表明，20-40平的曝光效率（曝光效率/租金预算）最高");
        }
        if (!data.getIsFillDayActiveBudget()) {
            addNum = slideAddMsgShape(slide, addNum, "单场预算", "5万-10万/月", "数据表明，20-40平的曝光效率（曝光效率/租金预算）最高");
        }

    }

    /**
     * 拼装结束页幻灯片
     */
    private void assembleEndSlide() {
        // 0608版本中该幻灯片页保持模版幻灯片不修改
        slideIndex++;
        return;
    }

    /**
     * 填充场地清单幻灯片
     *
     * @param spotList      点位集合
     * @param spotListIndex 点位集合下标
     * @param slide         幻灯片
     * @return 本次填充后点击集合下标
     */
    private int buildSpotSlide(List<RequirementPptData.SpotData> spotList, int spotListIndex, XSLFSlide slide) {
        for (XSLFShape shape : slide.getShapes()) {
            if (shape instanceof XSLFTextBox) {
                XSLFTextBox textBox = (XSLFTextBox) shape;
                if (CollUtil.isNotEmpty(textBox.getTextParagraphs()) && CollUtil.isNotEmpty(textBox.getTextParagraphs().get(0).getTextRuns())) {
                    String text = textBox.getText();
                    if (text.contains(RequirementPptPlaceholderEnum.TARGET_INFO.getValue()) || text.contains(RequirementPptPlaceholderEnum.RECOMMEND_NUM.getValue())) {
                        textBox.setText("");
                        // 字体设置
                        XSLFTextParagraph paragraph = textBox.getTextParagraphs().get(0);
                        XSLFTextRun textRun = paragraph.addNewTextRun();
                        textRun.setText("根据 ");
                        textRun.setFontColor(Color.BLACK);
                        textRun.setFontSize(20.00);
                        textRun.setBold(false);
                        XSLFTextRun textRun2 = paragraph.addNewTextRun();
                        textRun2.setText(ObjectUtil.isNotEmpty(data.getTargetInfo()) ? data.getTargetInfo() : "");
                        textRun2.setFontColor(Color.BLUE);
                        textRun2.setFontSize(20.00);
                        textRun2.setBold(false);
                        XSLFTextRun textRun3 = paragraph.addNewTextRun();
                        textRun3.setText(" 条件为您推荐如下" + (ObjectUtil.isNotEmpty(spotList) ? String.valueOf(spotList.size()) : "0") + "个场地：");
                        textRun3.setFontColor(Color.BLACK);
                        textRun3.setFontSize(20.00);
                        textRun3.setBold(false);
                    }
                }
            } else if (shape instanceof XSLFTable) {
                // 填充表格内数据
                XSLFTable table = (XSLFTable) shape;
                // 因为首行是标题，故从第二行开始（下标起始为0）
                for (int row = 1; row < table.getNumberOfRows(); row++) {
                    if (spotListIndex >= spotList.size()) {
                        break;
                    }
                    RequirementPptData.SpotData spotData = spotList.get(spotListIndex++);
                    for (int colum = 0; colum < table.getNumberOfColumns(); colum++) {
                        // 遍历单元格匹配修改内容
                        XSLFTableCell cell = table.getCell(row, colum);
                        String text = "";
                        // 序号
                        if (colum == 0) {
                            text = String.valueOf(spotListIndex);
                        }
                        // 城市
                        if (colum == 1) {
                            text = spotData.getCity();
                        }
                        // 行政区
                        if (colum == 2) {
                            text = spotData.getDistrict();
                        }
                        // 类型
                        if (colum == 3) {
                            text = spotData.getCategory();
                        }
                        // 场地名称
                        if (colum == 4) {
                            text = spotData.getPlaceName();
                        }
                        // 展位位置
                        if (colum == 5) {
                            text = spotData.getName();
                        }
                        // 楼层
                        if (colum == 6) {
                            text = spotData.getFloor();
                        }
                        // 面积
                        if (colum == 7) {
                            text = spotData.getArea();
                        }
                        // 客流
                        if (colum == 8) {
                            text = spotData.getWeekdaysFlow();
                        }
                        XSLFTextRun textRun = cell.setText(text);
                        // 添加超链接
                        if (colum == 4) {
                            XSLFHyperlink hyperlink = textRun.createHyperlink();
                            hyperlink.setAddress(spotData.getPlaceDetailUri());
                        }
                        if (colum == 5) {
                            XSLFHyperlink hyperlink = textRun.createHyperlink();
                            hyperlink.setAddress(spotData.getSpotDetailUri());
                        }
                    }
                }
            }
        }
        if (ObjectUtil.isNotEmpty(data.getPlaceListMapUri())) {
            slideAddLink(slide, new Rectangle2D.Double(780, 460, 200, 20), "点此在地图中查看", data.getPlaceListMapUri());
        }
        return spotListIndex;
    }

    /**
     * 幻灯片添加超链接
     *
     * @param slide       幻灯片
     * @param rectangle2D 矩形的位置以及大小
     * @param text        内容
     * @param address     链接地址
     */
    private void slideAddLink(XSLFSlide slide, Rectangle2D rectangle2D, String text, String address) {
        XSLFTextBox allActivityUriTextBox = slide.createTextBox();
        allActivityUriTextBox.setVerticalAlignment(VerticalAlignment.BOTTOM);
        allActivityUriTextBox.setAnchor(rectangle2D);
        XSLFTextRun r = allActivityUriTextBox.addNewTextParagraph().addNewTextRun();
        r.setText(text);
        r.setBold(false);
        r.setFontSize(16.00);
        XSLFHyperlink link = r.createHyperlink();
        link.setAddress(address);
    }

    /**
     * 幻灯片添加文本
     *
     * @param slide             幻灯片
     * @param rectangle2D       矩形的位置以及大小
     * @param text              内容
     * @param verticalAlignment 垂直对齐方式
     * @param isBold            是否加粗
     * @param fontSize          字号
     * @param fontColor         字体颜色
     */
    private void slideAddText(XSLFSlide slide, Rectangle2D rectangle2D, String text, VerticalAlignment verticalAlignment, Boolean isBold, Double fontSize, Color fontColor) {
        XSLFTextBox textBox = slide.createTextBox();
        textBox.setText(text);
        textBox.setVerticalAlignment(verticalAlignment);
        textBox.setAnchor(rectangle2D);
        XSLFTextParagraph paragraph = textBox.getTextParagraphs().get(0);
        paragraph.setTextAlign(TextParagraph.TextAlign.LEFT);
        XSLFTextRun textRun = paragraph.getTextRuns().get(0);
        if (fontColor != null) {
            textRun.setFontColor(fontColor);
        }
        textRun.setBold(isBold);
        textRun.setFontSize(fontSize);
    }

    /**
     * 幻灯片添加提示矩形
     *
     * @param slide   幻灯片
     * @param addNum  当前提示矩形数量
     * @param title   标题
     * @param example 例子
     * @param context 内容
     * @return 当前提示矩形数量
     */
    private int slideAddMsgShape(XSLFSlide slide, Integer addNum, String title, String example, String context) {
        if (addNum == null) {
            return 0;
        }
        XSLFAutoShape rectangle = slide.createAutoShape();
        // 设置矩形的位置和大小
        rectangle.setAnchor(new Rectangle2D.Double(30 + (addNum * 235), 210, 205, 280));
        // 设置矩形的填充颜色为黄色
        rectangle.setFillColor(new Color(242, 242, 242));
        slideAddText(slide, new Rectangle2D.Double(50 + (addNum * 235), 230, 180, 50), title, VerticalAlignment.TOP, false, 24.00, null);
        slideAddText(slide, new Rectangle2D.Double(50 + (addNum * 235), 300, 180, 50), example, VerticalAlignment.TOP, false, 24.00, new Color(3, 106, 255));
        slideAddText(slide, new Rectangle2D.Double(50 + (addNum * 235), 370, 180, 150), context, VerticalAlignment.TOP, false, 18.00, new Color(125, 125, 125));
        return addNum + 1;
    }

    /**
     * 复制ppt单页
     *
     * @param ppt      ppt
     * @param slide    复制原幻灯片
     * @param newIndex 复制页放置位置
     * @return 复制至幻灯片
     */
    private XSLFSlide copySlide(XMLSlideShow ppt, XSLFSlide slide, int newIndex) {
        // 创建新的一页PPT，按模板的布局
        XSLFSlide newSlide = ppt.createSlide().importContent(slide);
        // 排序（在PPT中的第几页）
        ppt.setSlideOrder(newSlide, newIndex);
        return newSlide;
    }

    /**
     * 在指定位置插入一张点位列表幻灯片
     *
     * @param newIndex      位置下标
     * @param spotList      位置下标
     * @param spotListIndex 位置下标
     * @return
     */
    private Integer insertSpotListSlide(Integer newIndex, List<RequirementPptData.SpotData> spotList, Integer spotListIndex) {
        XSLFSlide newSlide = ppt.createSlide();
        newSlide.clear();
        XSLFAutoShape rectangle = newSlide.createAutoShape();
        rectangle.setAnchor(new Rectangle2D.Double(0, 42, 30, 30));
        rectangle.setFillColor(new Color(22, 102, 240));
        slideAddText(newSlide, new Rectangle2D.Double(40, 42, 200, 30), "场地推荐清单", VerticalAlignment.MIDDLE, true, 28.00, null);
        if (ObjectUtil.isNotEmpty(data.getPlaceListMapUri())) {
            slideAddLink(newSlide, new Rectangle2D.Double(780, 490, 200, 20), "点此在地图中查看", data.getPlaceListMapUri());
        }
        // 表格
        String[] titles = new String[]{"序号", "城市", "行政区", "类型", "场地名称", "展位位置", "楼层", "面积", "客流"};
        XSLFTable table = newSlide.createTable(7, titles.length);
        table.setAnchor(new Rectangle2D.Double(30, 100, 700, 500));
        for (int r = 0; r < table.getRows().size(); r++) {
            table.setRowHeight(r, 50);
        }
        // 设置列宽
        table.setColumnWidth(0, 50);
        table.setColumnWidth(1, 75);
        table.setColumnWidth(2, 75);
        table.setColumnWidth(3, 75);
        table.setColumnWidth(4, 160);
        table.setColumnWidth(5, 160);
        table.setColumnWidth(6, 100);
        table.setColumnWidth(7, 100);
        table.setColumnWidth(8, 100);
        XSLFTableRow titleRow = table.getRows().get(0);
        for (int i = 0; i < titleRow.getCells().size(); i++) {
            XSLFTableCell cell = titleRow.getCells().get(i);
            cell.setFillColor(new Color(22, 102, 240));
            cell.setBorderColor(TableCell.BorderEdge.top, new Color(211, 211, 211));
            cell.setBorderColor(TableCell.BorderEdge.bottom, new Color(211, 211, 211));
            cell.setBorderColor(TableCell.BorderEdge.left, new Color(211, 211, 211));
            cell.setBorderColor(TableCell.BorderEdge.right, new Color(211, 211, 211));
            cell.setVerticalAlignment(VerticalAlignment.MIDDLE);
            XSLFTextRun textRun = cell.setText(titles[i]);
            textRun.setFontColor(Color.WHITE);
            textRun.setBold(Boolean.TRUE);
            textRun.setFontSize(14.00);
        }
        // 因为首行是标题，故从第二行开始（下标起始为0）
        for (int row = 1; row < table.getNumberOfRows(); row++) {
            if (spotListIndex >= spotList.size()) {
                break;
            }
            RequirementPptData.SpotData spotData = spotList.get(spotListIndex++);
            for (int colum = 0; colum < table.getNumberOfColumns(); colum++) {
                // 遍历单元格匹配修改内容
                XSLFTableCell cell = table.getCell(row, colum);
                cell.setBorderColor(TableCell.BorderEdge.top, new Color(211, 211, 211));
                cell.setBorderColor(TableCell.BorderEdge.bottom, new Color(211, 211, 211));
                cell.setBorderColor(TableCell.BorderEdge.left, new Color(211, 211, 211));
                cell.setBorderColor(TableCell.BorderEdge.right, new Color(211, 211, 211));
                cell.setVerticalAlignment(VerticalAlignment.MIDDLE);
                String text = "";
                // 序号
                if (colum == 0) {
                    text = String.valueOf(spotListIndex);
                }
                // 城市
                if (colum == 1) {
                    text = spotData.getCity();
                }
                // 行政区
                if (colum == 2) {
                    text = spotData.getDistrict();
                }
                // 类型
                if (colum == 3) {
                    text = spotData.getCategory();
                }
                // 场地名称
                if (colum == 4) {
                    text = spotData.getPlaceName();
                }
                // 展位位置
                if (colum == 5) {
                    text = spotData.getName();
                }
                // 楼层
                if (colum == 6) {
                    text = spotData.getFloor();
                }
                // 面积
                if (colum == 7) {
                    text = spotData.getArea();
                }
                // 客流
                if (colum == 8) {
                    text = spotData.getWeekdaysFlow();
                }
                XSLFTextRun textRun = cell.setText(text);
                // 添加超链接
                if (colum == 4) {
                    XSLFHyperlink hyperlink = textRun.createHyperlink();
                    hyperlink.setAddress(spotData.getPlaceDetailUri());
                }
                if (colum == 5) {
                    XSLFHyperlink hyperlink = textRun.createHyperlink();
                    hyperlink.setAddress(spotData.getSpotDetailUri());
                }
                textRun.setFontColor(Color.BLACK);
                textRun.setBold(Boolean.FALSE);
                textRun.setFontSize(14.00);
            }
        }
        // 排序（在PPT中的第几页）
        ppt.setSlideOrder(newSlide, newIndex);
        return spotListIndex;
    }

    /**
     * 上传文件至七牛云
     *
     * @param ppt 需要存储的PPT文件
     * @return PPT文件于七牛云的存储路径
     */
    protected String uploadFileToOss(XMLSlideShow ppt) {
        File file = new File("/Users/gwh/Documents/Linhuiba/demo/poi-ppt/src/main/resources/static/" + data.getRequirementName() + "场地推荐清单.pptx");
        if (file != null) {
            file.delete();
        }
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream("/Users/gwh/Documents/Linhuiba/demo/poi-ppt/src/main/resources/static/" + data.getRequirementName() + "场地推荐清单.pptx");
            ppt.write(fos);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                ppt.close();
                fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return "uri";
    }

    /**
     * 下载文件并返回流
     *
     * @param uri 文件链接
     * @return InputStream
     */
    protected InputStream getInputStream(String uri) {
        try {
            OkHttpClient client = new OkHttpClient();
            Request req = new Request.Builder().url(uri).build();
            Response resp = client.newCall(req).execute();
            ResponseBody body;
            if (resp.isSuccessful() && (body = resp.body()) != null) {
                return body.byteStream();
            } else {
                return null;
            }
        } catch (IOException e) {
            log.warn("生成需求PPT失败,加载资源失败.e:{}", e.getMessage());
            return null;
        }
    }

}
